<!--
 * @Autor: Ruohong Yu
 * @Date: 2022-09-01 20:08:37
 * @Description: file content
 * @FilePath: \ebook\src\components\ebook\EbookReader.vue
-->
<template>
  <div class="ebook-reader">
    <div id="read"></div>
    <div class="ebook-reader-mask"
         @click="onMaskClick"
         @touchmove="move"
         @touchend="moveEnd"
         @mousedown.left="onMouseEnter"
         @mousemove.left="onMouseMove"
         @mouseup="onMouseEnd"></div>
  </div>
</template>

<script>
import { ebookMixin } from '../../utils/mixin'
import {
  saveFontFamily,
  getFontFamily,
  saveFontSize,
  getFontSize,
  saveTheme,
  getTheme,
  getLocation
} from '../../utils/localStorage'
import Epub from 'epubjs'
import { flatten } from '@/utils/book'
import { getLocalForage } from '@/utils/localForage'

global.ePub = Epub

export default {
  mixins: [ebookMixin],
  mounted () {
    const books = this.$route.params.fileName.split('|')
    const fileName = books[1]
    getLocalForage(fileName, (err, blob) => {
      if (!err && blob) {
      // 找到缓存电子书
        this.setFileName(books.join('/')).then(() => {
          this.initEpub(blob)
        })
      } else {
        // 获取在线电子书
        this.setFileName(this.$route.params.fileName.split('|').join('/'))
          .then(() => {
            const url = `${process.env.VUE_APP_EPUB_URL}/` + this.fileName + '.epub'
            this.initEpub(url)
          })
      }
    })
  },
  sockets: {
    openCamera (res) {
      if (res === 'next') {
        this.jieliu(this.handNext, 500)
      } else if (res === 'last') {
        this.jieliu(this.handPrev, 500)
      }
    }
  },
  data () {
    return {
      timer: null
    }
  },
  methods: {
    handNext () {
      this.setHandState(1)
      this.nextPage()
    },
    handPrev () {
      this.setHandState(2)
      this.prevPage()
    },
    // 鼠标左键按下 this.mouseState=1
    // 鼠标左键按下并移动 this.mouseState=2
    // 鼠标左键从移动状态下松开 this.mouseState=3
    // 鼠标左键按下不移动就松开 this.mouseState=4
    onMouseEnter (e) {
      this.mouseState = 1
      this.mouseStartTime = e.timeStamp
      e.preventDefault()
      e.stopPropagation()
    },
    onMouseMove (e) {
      if (this.mouseState === 1) {
        this.mouseState = 2
      } else if (this.mouseState === 2) {
        let offsetY_ = 0
        if (this.firstOffsetY) {
          offsetY_ = e.clientY - this.firstOffsetY
          this.setOffsetY(offsetY_)
        } else {
          this.firstOffsetY = e.clientY
        }
      }
      e.preventDefault()
      e.stopPropagation()
    },
    onMouseEnd (e) {
      if (this.mouseState === 2) {
        this.setOffsetY(0)
        this.firstOffsetY = null
        this.mouseState = 3
      } else {
        this.mouseState = 4
      }
      const time = e.timeStamp - this.mouseStartTime
      if (time < 200) {
        this.mouseState = 4
      }
      e.preventDefault()
      e.stopPropagation()
    },
    move (e) {
      let offsetY_ = 0
      if (this.firstOffsetY) {
        offsetY_ = e.touches[0].clientY - this.firstOffsetY
        this.setOffsetY(offsetY_)
      } else {
        this.firstOffsetY = e.changedTouches[0].clientY
      }
      // 禁用默认方法调用防止微信端下拉出错
      e.preventDefault()
      // 禁止传播
      e.stopPropagation()
    },
    moveEnd (e) {
      this.setOffsetY(0)
      this.firstOffsetY = null
    },
    onMaskClick (e) {
      if (this.mouseState && (this.mouseState === 2 || this.mouseState === 3)) {
        return
      }
      const offsetX = e.offsetX
      const width = window.innerWidth
      if (offsetX > 0 && offsetX < width * 0.3) {
        this.prevPage()
      } else if (offsetX > 0 && offsetX > width * 0.7) {
        this.nextPage()
      } else {
        this.toggleTitleAndMenu()
      }
    },
    prevPage () {
      if (this.rendition) {
        this.rendition.prev().then(() => {
          this.refreshLocation()
        })
        this.hideTitleAndMenu()
      }
    },
    nextPage () {
      if (this.rendition) {
        this.rendition.next().then(() => {
          this.refreshLocation()
        })
        this.hideTitleAndMenu()
      }
    },
    toggleTitleAndMenu () {
      if (this.menuVisible) {
        this.setSettingVisible(-1)
        this.setFontFamilyVisible(false)
      }
      // this.$store.dispatch('setMenuVisible', !this.menuVisible)
      this.setMenuVisible(!this.menuVisible)
    },

    initFontSize () {
      const fontSize = getFontSize(this.fileName)
      if (!fontSize) {
        saveFontSize(this.fileName, this.defaultFontSize)
        this.rendition.themes.fontSize('16')
      } else {
        this.rendition.themes.fontSize(fontSize)
        this.setDefaultFontSize(fontSize)
      }
    },
    initFontFamily () {
      const font = getFontFamily(this.fileName)
      if (!font) {
        saveFontFamily(this.fileName, this.defaultFontFamily)
        this.rendition.themes.font('Times New Roman')
      } else {
        this.rendition.themes.font(font)
        this.setDefaultFontFamily(font)
      }
    },
    initTheme () {
      let defaultTheme = getTheme(this.fileName)
      if (!defaultTheme) {
        defaultTheme = this.themeList[0].name
        saveTheme(this.fileName, defaultTheme)
      }
      this.setDefaultTheme(defaultTheme)
      this.initGlobalStyle()
      this.themeList.forEach(theme => {
        this.rendition.themes.register(theme.name, theme.style)
      })
      this.rendition.themes.select(defaultTheme)
    },
    initRendition () {
      this.rendition = this.book.renderTo('read', {
        width: window.innerWidth,
        height: window.innerHeight,
        method: 'default'
      })
      // 通过localStorage保存用户的设置和阅读信息，即刷新后不会恢复默认样式
      const location = getLocation(this.fileName)
      this.display(location, () => {
        this.initFontSize()
        this.initFontFamily()
        this.initGlobalStyle()
        this.initTheme()
      })

      // 注册字体样式文件
      this.rendition.hooks.content.register(contens => {
        Promise.all([
          contens.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/daysOne.css`),
          contens.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/cabin.css`),
          contens.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/montserrat.css`),
          contens.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/tangerine.css`)
        ]).then(() => {
        })
      })
    },
    // initGesture () {
    //   this.rendition.on('touchstart', event => {
    //     this.touchStartX = event.changedTouches[0].clientX
    //     this.touchStartTime = event.timeStamp
    //     console.log(this.touchStartX + ' ' + this.touchStartTime)
    //   })
    //   this.rendition.on('touchend', event => {
    //     const offsetX = event.changedTouches[0].clientX - this.touchStartX
    //     const time = event.timeStamp - this.touchStartTime
    //     console.log(offsetX + ' ' + time)
    //     if (time < 500 && offsetX > 40) {
    //       // 向右滑
    //       this.prevPage()
    //     } else if (time < 500 && offsetX < -40) {
    //       // 向左滑
    //       this.nextPage()
    //     } else {
    //       // 单击屏幕
    //       this.toggleTitleAndMenu()
    //     }
    //     // 禁用默认方法调用
    //     event.preventDefault()
    //     // 禁止传播
    //     event.stopPropagation()
    //   })
    // },
    parseBook () {
      this.book.loaded.cover.then(cover => {
        this.book.archive.createUrl(cover).then(url => {
          this.setCover(url)
        })
      })
      this.book.loaded.metadata.then(metadata => {
        this.setMetadata(metadata)
      })
      this.book.loaded.navigation.then(nav => {
        const navItem = flatten(nav.toc)
        function find (item, level = 0) {
          return !item.parent ? level : find(navItem.filter(parentItem => parentItem.id === item.parent)[0], ++level)
        }
        navItem.forEach(item => {
          item.level = find(item)
        })
        this.setNavigation(navItem)
      })
    },
    initEpub (url) {
      this.book = new Epub(url)
      this.setCurrentBook(this.book)

      this.initRendition()
      // this.initGesture()
      this.parseBook()

      // 分页算法
      this.book.ready.then(() => {
        // 随着屏幕宽度和字体大小的变化决定一页出现的字数
        return this.book.locations.generate(750 * (window.innerWidth / 375) * (getFontSize(this.fileName) / 16))
      }).then(locations => {
        this.setBookAvailable(true)
        this.refreshLocation()
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.ebook-reader {
  width: 100%;
  height: 100%;
  overflow: hidden;
  .ebook-reader-mask {
    position: absolute;
    z-index: 150;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
}
</style>
